﻿Imports System.ServiceModel
Imports System.Threading
Imports Org.BouncyCastle.Crypto
Imports System.ComponentModel
Imports System.ServiceModel.Discovery

Class MainWindow
    Implements INotifyPropertyChanged

    Public Shared Property Timer As New Timers.Timer

    Public Shared Sub InitializeRefreshCycle()
        Timer.AutoReset = True
        Timer.Interval = 5000
        AddHandler Timer.Elapsed, AddressOf CRLManager.RefreshCRL
        AddHandler Timer.Elapsed, AddressOf CertificatesManager.RefreshCertificatesStatus
        Timer.Start()
    End Sub


    Public ReadOnly Property PasswordsOk As Boolean
        Get
            Return passBox.Password = passBoxRepeat.Password AndAlso Not String.IsNullOrWhiteSpace(passBox.Password)
        End Get
    End Property
    Public ReadOnly Property UnlockEnabled As Boolean
        Get
            Return Not String.IsNullOrWhiteSpace(passUnlock.Password)
        End Get
    End Property


    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim host As New ServiceHost(GetType(MessagesService))
        host.Description.Behaviors.Add(New ServiceDiscoveryBehavior())
        host.AddServiceEndpoint(New UdpDiscoveryEndpoint())
        host.Open()

        If PersistenceManager.IsDataPresent Then
            'Data is present
            ShowUnlock()
        Else
            'first run
            ShowFirstRun()
        End If


    End Sub

    Private Sub ShowFirstRun()
        stackFirstRun.Visibility = Windows.Visibility.Visible
        stackGenerating.Visibility = Windows.Visibility.Collapsed
        tabMain.Visibility = Windows.Visibility.Collapsed
        stackPassword.Visibility = Windows.Visibility.Collapsed
    End Sub

    Private Sub ShowGenerating()
        stackFirstRun.Visibility = Windows.Visibility.Collapsed
        stackGenerating.Visibility = Windows.Visibility.Visible
        tabMain.Visibility = Windows.Visibility.Collapsed
        stackPassword.Visibility = Windows.Visibility.Collapsed
    End Sub

    Private Sub ShowMain()
        stackFirstRun.Visibility = Windows.Visibility.Collapsed
        stackGenerating.Visibility = Windows.Visibility.Collapsed
        tabMain.Visibility = Windows.Visibility.Visible
        stackPassword.Visibility = Windows.Visibility.Collapsed
        buttonMyCert.Visibility = Windows.Visibility.Visible

        If tabRequests.Content Is Nothing Then
            tabRequests.Content = New RequestsGrid(Repository.Requests)
        End If
        If tabCertificates.Content Is Nothing Then
            tabCertificates.Content = New CertificatesGrid(Repository.Certificates)
        End If
        InitializeRefreshCycle()
    End Sub

    Private Sub ShowUnlock()
        stackFirstRun.Visibility = Windows.Visibility.Collapsed
        stackGenerating.Visibility = Windows.Visibility.Collapsed
        tabMain.Visibility = Windows.Visibility.Collapsed
        stackPassword.Visibility = Windows.Visibility.Visible
    End Sub

    Private Sub CertificateReady()
        If Me.Dispatcher.Thread IsNot Thread.CurrentThread Then
            Me.Dispatcher.BeginInvoke(New CertificateReadyDelegate(AddressOf CertificateReady), {})
            Return
        End If

        RemoveHandler MyCertificateManager.CertificateGenerated, AddressOf CertificateReady
        stackFirstRun.Visibility = Windows.Visibility.Collapsed
        stackGenerating.Visibility = Windows.Visibility.Collapsed
        tabMain.Visibility = Windows.Visibility.Visible
        ShowMain()
    End Sub

    Delegate Sub CertificateReadyDelegate()

    Private Sub GenerateKey_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        Repository.Password = passBox.Password
        AsyncGenerateCert()
        ShowGenerating()
        e.Handled = True
    End Sub

    Private Sub AsyncGenerateCert()
        'generate key & certificate
        AddHandler MyCertificateManager.CertificateGenerated, AddressOf CertificateReady
        Dim doWork As WaitCallback = New WaitCallback(AddressOf MyCertificateManager.GenerateMyCertificate)
        ThreadPool.QueueUserWorkItem(doWork, 4096) 'TODO: change back to 4096!!!
        Return
    End Sub

    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    Private Overloads Sub OnPropertyChanged(name As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
    End Sub

    Private Sub passBox_PasswordChanged(sender As System.Object, e As System.Windows.RoutedEventArgs)
        If sender Is passUnlock Then
            OnPropertyChanged("UnlockEnabled")
        Else
            OnPropertyChanged("PasswordsOk")
        End If

    End Sub

    Private Sub Exit_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        Me.Close()
        e.Handled = True
    End Sub

    Private Sub buttonUnlock_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        'try to load data
        Repository.Password = passUnlock.Password

        Try
            PersistenceManager.LoadAll()
        Catch ex As Ionic.Zip.BadPasswordException
            MessageBox.Show("Password is incorrect! Please try again", "Bad Password", MessageBoxButton.OK, MessageBoxImage.Warning)
            Return
        Catch ex As PersistenceManager.CertificateExpiredException
            Dim result = MessageBox.Show("Your certificate is expired!! The CA will now generate A new one. Do you wish to proceed?", "CA certifiate expired", MessageBoxButton.YesNo, MessageBoxImage.Question)
            If result = MessageBoxResult.No Then
                Me.Close()
                Return
            End If
            ShowFirstRun()
            Return
        End Try

        ShowMain()
    End Sub

    Private Sub ComboLife_SelectionChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs)
        If sender Is comboCertLife Then
            My.Settings.CertsLife = CInt(DirectCast(comboCertLife.SelectedItem, ComboBoxItem).Tag)
        Else
            My.Settings.CRLLife = CInt(DirectCast(comboCRLLife.SelectedItem, ComboBoxItem).Tag)
        End If
        My.Settings.Save()
    End Sub

    Private Sub buttonMyCert_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        CertificatesManager.ShowCertificateDetails(Repository.Data.MyCertificate)
    End Sub
End Class
